﻿using System.Text;
using System;
namespace Framework.Common.Html
{
    public class Html2Summary
    {
        private int _truncate;
        private readonly HtmlDocument _doc;
        private bool _stop;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        public Html2Summary(string input)
        {
            _doc = new HtmlDocument();
            _doc.LoadHtml(input);
        }

        /// <summary>
        /// ConvertHtml
        /// </summary>
        /// <param name="truncateLength"> </param>
        /// <returns></returns>
        public string Truncate(int truncateLength)
        {
            _truncate = truncateLength;
            var sbTxt = new StringBuilder();
            VisitFor(_doc.DocumentNode, sbTxt);
            return sbTxt.ToString();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <param name="outText"></param>
        void VisitFor(HtmlNode node, StringBuilder outText)
        {
            switch (node.NodeType)
            {
                case HtmlNodeType.Document:
                    VisitForSubs(node, outText);
                    break;

                case HtmlNodeType.Text:
                    // script and style must not be output
                    string parentName = node.ParentNode.Name;
                    if ((parentName == "script") || (parentName == "style"))   return;
                    // get text
                    string html = ((HtmlTextNode)node).Text;
                    // is it in fact a special closing node output as text?
                    if (HtmlNode.IsOverlappedClosingElement(html)) return;
                    // check the text is meaningful and not a bunch of whitespaces
                    if (!string.IsNullOrWhiteSpace(html))
                    {
                        string tmpToken = HtmlEntity.DeEntitize(html).Trim();
                        int tokenLength = tmpToken.StringLength();
                        int remainder = _truncate - tokenLength;
                        if (remainder >= 0)
                        {
                            outText.Append(tmpToken);
                            _truncate = remainder;
                        }
                        else
                        {
                            outText.Append(tmpToken.CutStringCN(_truncate));
                            _stop = true;
                        }
                    }
                    break;

                case HtmlNodeType.Element:
                    if (node.HasChildNodes)
                    {
                        VisitForSubs(node, outText);
                    }
                    break;
            }
        }

        void VisitForSubs(HtmlNode node, StringBuilder outText)
        {
            foreach (HtmlNode subnode in node.ChildNodes)
            {
                if (_stop) break;
                VisitFor(subnode, outText);
            }
        }

    }
}
